package com.common;
/*

                  写字楼里写字间，写字间里程序员；
                  程序人'猿'写程序，又拿程序换酒钱。
                  酒醒只在网上坐，酒醉还来网下眠；
                  酒醉酒醒日复日，网上网下年复年。
                  但愿老死电脑间，不愿鞠躬老板前；
                  奔驰宝马贵者趣，公交自行程序员。
                  别人笑我忒疯癫，我笑自己命太贱；
                  不见满街漂亮妹，哪个归得程序'猿'？
━━━━━━神兽出没━━━━━━
 ┏┓   ┏┓
┏┛┻━━━┛┻┓
┃       ┃
┃   ━   ┃
┃ ┳┛ ┗┳ ┃
┃       ┃
┃   ┻   ┃
┃       ┃
┗━┓   ┏━┛
  ┃   ┃                    神兽保佑, 永无BUG!
  ┃   ┃       Code is far away from bug with the animal protecting
  ┃   ┗━━━┓
  ┃       ┣┓
  ┃       ┏┛
  ┗┓┓┏━┳┓┏┛
   ┃┫┫ ┃┫┫
   ┗┻┛ ┗┻┛
 */

import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by 石头哥哥 on 5/3/16.
 * <p>
 * common
 * <p>
 * com.common
 * <p>
 * comments:   mongodb 服务类
 * <p>
 * 处理geo ,存储文件gridfs,存储二进制数据
 */
@Component
public class MongoService {

    private final String databaseName;
    private final String host;
    private int port;
    private MongoClient mongoClient;
    private MongoDatabase mongoDatabase;
    private GridFS gridFS = null;


    /**
     * 存储数据建议直接用 BasicBSONObject
     */

    /**
     * 构造函数<p/>
     *
     * @param databaseName db
     * @param host         127.0.0.1
     * @param port         27017
     */
    public MongoService(final String databaseName, final String host, final int port) {
        this.databaseName = databaseName;
        this.host = host;
        this.port = port;
        this.mongoClient = new MongoClient(host, port);
        this.mongoDatabase = mongoClient.getDatabase(this.databaseName);
    }


    /**
     * @param databaseName 数据库名称
     * @param host         主机
     * @param options      mongo 参数设置----- 参考官方文档进行设置,默认采用确定内部缺省值
     */
    public MongoService(final String databaseName, final String host, final MongoClientOptions options) {
        this.databaseName = databaseName;
        this.host = host;
        this.mongoClient = new MongoClient(new ServerAddress(host), options);
        this.mongoDatabase = mongoClient.getDatabase(this.databaseName);
    }


    /**
     * 创建gridfs 对象 用于 存储文件
     *
     * @param bucket 存储文件集合名(容器)
     * @return
     */
    public GridFS getGridFs(String bucket) {
        synchronized (this) {
            if (gridFS == null) {// null
                gridFS = new GridFS(new DB(mongoClient, bucket));//
            }
        }
        return gridFS;// not null
    }


    /**
     * @param id
     * @param in
     * @param filename
     * @param bucket
     */
    public void save(Object id, InputStream in, String filename, String bucket) throws IOException {
        GridFS gridFS = getGridFs(bucket);
        GridFSInputFile gridFSInputFile = gridFS.createFile(in, filename);
        gridFSInputFile.setId(id);
        gridFSInputFile.setFilename(filename);
        gridFSInputFile.setChunkSize(in.available());
        gridFSInputFile.save();
    }


    /**
     * 获取数据操作引用
     *
     * @return
     */
    public MongoDatabase database() {
        return this.mongoDatabase;
    }


    /**
     * 获取操作数据表
     *
     * @param collectionName 文档集合名  ---- 表名称
     * @return
     */
    public MongoCollection<Document> getCollection(final String collectionName) {
        return this.mongoDatabase.getCollection(collectionName);
    }


    /**
     * 获取操作集合
     *
     * @param collectionName
     * @param codecRegistry  注册编解码器
     * @return
     */
    public MongoCollection<Document> getCollection(final String collectionName, final CodecRegistry codecRegistry) {
        return this.mongoDatabase.getCollection(collectionName).withCodecRegistry(codecRegistry);
    }

    /**
     * 定制编解码器,返回注册器
     *
     * @param codecs {@link MongoClient@getDefaultCodecRegistry();}
     * @return
     */
    public CodecRegistry codecRegistry(final Codec<?>... codecs) {
        return CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(codecs));
    }


}
